#ifndef _DAT_Manager_H_
#define _DAT_Manager_H_

//OpenCV Headers
#include "opencv.hpp"

//DATLib Headers
#include "DATFactory.h"
#include "TrackerFactory.h"
#include "Detector.h"
#include "Tracker.h"
#include "CvVision.h"
#include "XMLManager.h"

//LVSN Headers (OR NOT)
//#include <LVSN\Configuration.h>

//STL Headers
#include <list>
#include <string>
#include <iostream>

//XML headers
#include "tinyxml.h"

using namespace std;

//#define TEST_SEARCH_ONLY		//Only for calculating AFR

//#define DEFAULT_MATCH_TRESHOLD	0.2
//#define DEFAULT_POSE_CHANGING_TRESHOLD	0.2
//#define DEFAULT_DETECTED_AREA	0.4

class DATManager
{
public:
	//****	Constructor/Destructor	****//
	DATManager();
	DATManager(double inGeneralConfidenceThreshold, int inAliveThreshold, float inDeadThreshold);
	~DATManager();

	//****	Install function	****//
	//install functions, must be done before everything else
	void installDATFactory(DATFactory* inDATFactory);
	void installTrackerFactory(TrackerFactory* inTrackerFactory);
	void installDetectors(list<Detector*> inDetectors);
	void installXMLManager(XMLManager* inXMLManager);

	//****	Factory utils		****//
	bool isReady(){return (mDATFactory && mTrackerFactory && !mDetectors.empty());}

	//****	Video feed management	****//
	bool addVideoFeed(string inVideoFilename);
	
	//****	Detectors management	****//
	bool addDetector(Detector* inNewDetector);
	bool deleteDetector(string inObjectTypeName);

	//****	DATManager START function	****//
	//This is the BIG function... to be clean, create a CvVisualisator (NOT !) or little keyboard checking funtion(s)
	//It's a big "while (true)" function... almost... a lot of keyboard check... we want that thing to be interactive... sometime
	bool startUntilEOF(int inFrame = 0);
	//outNewDetection is all the detection found in that frame
	//outUpdatedTrackers is for N new object and the M that have been matched with an object or the frame (updated) 
	bool start(list<DATObject*>& outNewDetections, list<Tracker*>& outUpdatedTrackers, int inFrame); //Do only one frame. Usefull for test AND the CvVisualisator thingy

	//****	set/get functions	****//
	void setMatchingTreshold(double inMatchingThreshold){mMatchingThreshold = inMatchingThreshold;};
	void setDetectedAreaThreshold(double inDetectedAreaThreshold){mDetectedAreaThreshold = inDetectedAreaThreshold;};
	void setDetectionEnabled(bool inDetectionEnabled){mDetectionEnabled = inDetectionEnabled;};
	void setDoMatching(bool inDoMatching){mDoMatching = inDoMatching;};
	void setDoSearch(bool inDoSearch){mDoSearch = inDoSearch;};
	void changeDetectionEnabled(){mDetectionEnabled=!mDetectionEnabled;}
	void setTrimEnabled(bool inTrimEnabled){mTrimEnabled = inTrimEnabled;};
	void changeTrimEnabled(){mTrimEnabled=!mTrimEnabled;}
	void setTrackingEnabled(bool inTrackingEnabled){mTrackingEnabled = inTrackingEnabled;};
	void changeTrackingEnabled(){mTrackingEnabled=!mTrackingEnabled;}
	void setMergingEnabled(bool inMergingEnabled){mMergingEnabled = inMergingEnabled;};
	void changeMergingEnabled(){mMergingEnabled=!mMergingEnabled;}
	void setPredictionEnabled(bool inPredictionEnabled){mPredictionEnabled = inPredictionEnabled;};
	void changePredictionEnabled(){mPredictionEnabled=!mPredictionEnabled;}
	void setXMLSaveIn(bool inXMLSaveIn){mXMLSaveIn = inXMLSaveIn;};
	void changeXMLSaveIn(){mXMLSaveIn=!mXMLSaveIn;}
	const double getMatchingTreshold()const{return mMatchingThreshold;};
	const bool getDetectionEnabled()const{return mDetectionEnabled;}
	const bool getTrackingEnabled()const{return mTrackingEnabled;}
	const bool getTrimEnabled()const{return mTrimEnabled;}
	const bool getMergingEnabled()const{return mMergingEnabled;}
	const bool getPredictionEnabled()const{return mPredictionEnabled;}
	const bool getXMLSaveIn()const{return mXMLSaveIn;}
	const bool getDoMatching()const{return mDoMatching;}
	const bool getDoSearch()const{return mDoSearch;}
	CvVision* getVideoFeed(){return mVideoFeed;}	//BEWARE

	//**** Living state function ****//
	list<Tracker*> removeObjects(LivingState inState);
	void changeState(LivingState inState); //FOR ALL

	//****	Util functions	****//
	void clear();
	bool calculateOverlapArea(CvPoint* inPoint1,CvPoint* inPoint2, cv::Rect& outOverlap);
protected:
	//**** DATManager utility functions ****//
	//the return value is for error... if == 1, no prob.
	//if inFrame == -1, take the "actual" frame

	//Detectors are used in inFrame (if ==-1, current)
	int startDetectors(list<DATObject*>& outDetections);
	//Trim detections. If too much area is common, keep the one with the highest confidence.
	void trimDetections(list<DATObject*>& ioDetections);
	//Use the tracker on the new detection. Compare with tracker first and with frame afterward.
	int startTracking(const list<DATObject*>& inNewObjects, list<Tracker*>& outUpdatedTrackers);
	//Create tracker from DATObject not matched. Use the factory. (Seems useless)
	void createTracker(list<Tracker*>& outNewTrackers, list<DATObject*>& inDetections);	//by ref is not necessary ?
	//
	bool mergeTrackers(Tracker* ioTracker1, Tracker* inTracker2);

	//This 2 function are, for the "simple/sample" application, useless... 
	//someone with different detectors/trackers or ideas could derive DATManager 
	//and modify those functions that are called in the start() function.
	virtual bool preProcessing(){return true;};
	virtual bool postProcessing(){return true;};

private:
	list<Detector*>			mDetectors;			//List of big detector objects

	DATFactory*				mDATFactory;
	TrackerFactory*			mTrackerFactory;
	list<Tracker*>			mTrackedObjects;	//list of followed objects
	XMLManager*				mXMLManager;

	list<DATObject*>		mDeadObjects;		//All objects we don't follow anymore (but were real)

	CvVision*				mVideoFeed;

	//There will be a define for those, BUT, we can change each value
	double					mMatchingThreshold;	
	double					mDetectedAreaThreshold;
	double					mAliveConfidenceThreshold;
	int						mLifeCounterThreshold;
	float					mStartingDeathCounter;

	//To control each element of the "shell"
	bool					mDetectionEnabled;
	bool					mTrimEnabled;
	bool					mTrackingEnabled;
	bool					mPredictionEnabled;
	bool					mMergingEnabled;
	bool					mXMLSaveIn;
	bool					mDoMatching;
	bool					mDoSearch;
	
};

#endif